import type { Router } from 'vue-router';
import { useUserStore } from '/@/store/modules/user';
import { PageEnum } from '/@/enums/pageEnum';

const blackPathList: PageEnum[] = [];

export function createPermissionGuard(router: Router) {
  const userStore = useUserStore();

  router.beforeEach(async (to, from, next) => {
    const token = userStore.getToken;

    // token or user does not exist
    if (!token) {
      // BlackList can not be directly entered
      // You can not access without permission. You need to set the routing meta.requiredAuth to false
      if (blackPathList.includes(to.path as PageEnum) || to.meta.requiredAuth) {
        // redirect login page
        const redirectData: { path: string; replace: boolean; query?: Recordable<string> } = {
          path: PageEnum.HOME,
          replace: true,
        };

        const redirect = to.redirectedFrom?.fullPath || to.path;
        if (to.path) {
          redirectData.query = {
            ...redirectData.query,
            redirect,
          };
        }
        next(redirectData);
        userStore.goLogin();
        return;
      }
    }

    // redirect to previous page if you have token
    if (token && to.path === PageEnum.LOGIN) {
      try {
        await userStore.afterLoginAction();
        next((to.query?.redirect as string) || PageEnum.HOME);
        return;
      } catch {}
    }

    // get userinfo while last fetch time is empty
    if (token && userStore.getLastUpdateTime === 0) {
      try {
        await userStore.getUserInfoAction();
      } catch (err) {}
    }

    if (from.query.redirect) {
      if (to.path === from.query.redirect) {
        next();
        return;
      }
      const redirect = decodeURIComponent(from.query.redirect as string);
      const nextData: { path: string; replace?: boolean; query?: Recordable<string> } = {
        path: redirect,
      };
      if (to.path === redirect) {
        nextData.query = {
          ...to.query,
          redirect: '',
        };
        nextData.replace = true;
      }
      next(nextData);
      return;
    }

    next();
  });
}
